/*
 * NcxGenerator.java
 *
 *  created: 20.8.2011
 *  charset: UTF-8
 *  license: MIT (X11) (See LICENSE file for full license)
 */
package cz.mp.k3bg.core;

import static cz.mp.k3bg.Application.EOL;
import cz.mp.k3bg.log.LoggerManager;
import cz.mp.util.FileUtils;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.logging.Logger;


/**
 * Třída {@code NcxGenerator} vytváří soubor s navigací
 * (Navigation Control file for XML); vytváří se z Obsahu (ToC)
 * (a v podstatě obsahuje obsah v XML).
 * 
 * @author Martin Pokorný
 * @version 0.1
 */
public class NcxGenerator extends Generator {

    private static final boolean DEBUG = false;
    private static final Logger logger =
            LoggerManager.getLogger(NcxGenerator.class, DEBUG);
    
    // -----
    
    /**
     * 
     * @param bookFiles
     * @param metadata 
     */
    public NcxGenerator(BookFiles bookFiles, Metadata metadata) {
        super(bookFiles, metadata);
    }
    
    // -----
    
    /**
     * 
     * @throws IOException 
     */
    @Override
    public void generate() throws IOException {
        logger.info("");
                
        if (bookFiles.getNcx() == null) {
            throw new IllegalStateException("ncx=null");
        }
        if (bookFiles.getToc() == null) {
            throw new IllegalStateException("toc=null");
        }
              
        BufferedWriter writer = bookFiles.getNcx().getBufferedWriter();
        
        // sestavení souboru :
        writer.write(createNcxHeader());
        writer.flush();        
        
        int order = 1;      // číslování v NCX začíná od 1, ne od 0                
        for (Reference reference : bookFiles.getToc().getReferences()) {
            String navClass = getNavClassName(reference);
            
            writer.write(createNcxNavItem(reference, navClass, order));
            writer.flush();
            order++;
        }
        
        writer.write(createNcxFooter());
        writer.flush();
        
        writer.close();
        logger.fine("(finished!)");
    }
    
    /**
     * 
     * @param reference
     * @return   chapter / section / toc
     */
    private String getNavClassName(Reference reference) {
        logger.finest("");
        String navClass = "";
        
        if (isReferenceToFile(reference, bookFiles.getToc())) {
            navClass="toc";
        }
        else if (isReferenceToFile(reference, bookFiles.getColophon())) {
            navClass="section";
        }
        else if (isReferenceToFile(reference, bookFiles.getLoi())) {
            navClass="section";
        }
        else {
            navClass = "chapter";
        }
        
        return navClass;
    }
    
    /**
     * 
     * @param reference
     * @param file
     * @return 
     */
    private boolean isReferenceToFile(Reference reference, HtmlFile file) {
        if (reference == null) {
            throw new IllegalArgumentException("reference=null");
        }
        if (file != null && 
                reference.getUrl().equals(file.getPath())) {
            return true;
        }
        return false;
    }
    
    /**
     * 
     * @return 
     */
    private String createNcxHeader() {
        logger.finer("");
        StringBuilder sb = new StringBuilder(512);
        sb.append("<?xml version=\"1.0\" encoding=\"")
                .append(bookFiles.getNcx().getCharsetName()).append("\"?>");
        sb.append(EOL);
        sb.append("<!DOCTYPE ncx PUBLIC \"-//NISO//DTD ncx 2005-1//EN\" ")
                .append("\"http://www.daisy.org/z3986/2005/ncx-2005-1.dtd\">");
        sb.append(EOL);
        sb.append("<ncx xmlns=\"http://www.daisy.org/z3986/2005/ncx/\" ")
                .append("version=\"2005-1\" xml:lang=\"en\">");
        sb.append(EOL);
        sb.append("<head>");
        sb.append(EOL);
        sb.append("<meta name=\"dtb:uid\" content=\"")
                .append(metadata.getId()).append("\" />");
        sb.append(EOL);
        sb.append("<meta name=\"dtb:depth\" content=\"1\" />");
        sb.append(EOL);
        sb.append("<meta name=\"dtb:totalPageCount\" content=\"0\" />");
        sb.append(EOL);
        sb.append("<meta name=\"dtb:maxPageNumber\" content=\"0\" />");
        sb.append(EOL);
        sb.append("</head>");
        sb.append(EOL);
        sb.append("<docTitle><text>")
                .append(metadata.getTitle()).append("</text></docTitle>");
        sb.append(EOL);
        sb.append("<docAuthor><text>")
                .append(metadata.getAuthor()).append("</text></docAuthor>");
        sb.append(EOL);
        sb.append("<navMap>");
        sb.append(EOL);sb.append(EOL);        
        return sb.toString();
    }

    /**
     * 
     * @param reference
     * @param navClass
     * @param playOrder
     * @return 
     */
    private String createNcxNavItem(Reference reference, String navClass, 
            int playOrder) {
        logger.finer(" reference = " + reference 
                + "   playOrder = " + playOrder);

        StringBuilder sb = new StringBuilder(256);
        
        String myNavClass = navClass;
        String id = getIdFromFileRef(reference.getUrl());
        
        // --- <navPoint class=\"chapter\" id=\"ChapterWithAnchor-01\" playOrder=\"3\">
        sb.append("    <navPoint class=\"")
                .append(myNavClass)
                .append("\" id=\"").append(id)
                .append("\" playOrder=\"").append(playOrder)
                .append("\">");
        sb.append(EOL);
        
        // --- <navLabel><text>ChapterWithAnchor one</text></navLabel>
        sb.append("        <navLabel><text>")
                .append(reference.getValue()).append("</text></navLabel>");
        sb.append(EOL);
        
        // --- <content src=\"file.html#ChapterWithAnchor-01\"/>        
        sb.append("        <content src=\"")
                .append(reference.getUrl()).append("\" />");
        sb.append(EOL);
        
        // --- </navPoint>
        sb.append("    </navPoint>");
        sb.append(EOL).append(EOL);
        
        return sb.toString();
    }    
    
    /**
     * 
     * <tt><pre>
     * toc.html --> toc
     * test.html#ch01 --> ch01
     * </pre></tt>
     * 
     * @return 
     */
    private String getIdFromFileRef(String fileRef) {        
        if (fileRef.contains("#")) {
            return fileRef.substring(fileRef.indexOf("#") + 1);
        }
        else {
            return FileUtils.getFilePathWithoutExt(fileRef);
        }
    }
    
    private String createNcxFooter() {
        logger.finest("");
        StringBuilder sb = new StringBuilder();
        sb.append("</navMap>");
        sb.append(EOL);
        sb.append("</ncx>");
        sb.append(EOL);
        return sb.toString();
    }

}   // NcxGenerator
